package com.easylinkin.linkappapi.security.controller;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.annotation.CommonOperateLogAnnotate;
import com.easylinkin.linkappapi.application.service.ApplicationService;
import com.easylinkin.linkappapi.common.constant.CommonConstant;
import com.easylinkin.linkappapi.operatelog.LogHelper;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogModule;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogOperateType;
import com.easylinkin.linkappapi.security.entity.LinkappPrivilege;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.service.LinkappPrivilegeService;
import com.easylinkin.linkappapi.security.service.LinkappRoleService;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import com.easylinkin.linkappapi.tenant.dto.LinkappTenantDTO;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import com.easylinkin.sm.entity.User;
import com.easylinkin.sm.service.LoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import site.morn.boot.data.CrudControllerSupport;
import site.morn.boot.web.Responses;
import site.morn.framework.context.AccountContext;
import site.morn.framework.entity.BaseUser;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

/**
 * 登录控制器
 *
 * @author timely-rain
 * @since 1.0.0, 2019/8/15
 */
@Api(tags = "登录管理")
@RestController
@RequestMapping("/login")
public class LinkappLoginController extends CrudControllerSupport<User, Long, LoginService> {

  @Autowired
  private LinkappUserService userService;
  @Autowired
  private LinkappRoleService roleService;
  @Autowired
  private LinkappPrivilegeService privilegeService;
  @Autowired
  private ApplicationService applicationService;

  @Autowired
  private LinkappTenantService linkappTenantService;

  @Resource
  private RedisUtil redisUtil;

  /**
   * 获取当前用户信息
   *
   * @return REST消息
   */
  @ApiOperation("获取当前用户信息")
  @GetMapping("info")
  public RestMessage info() {
    BaseUser baseUser = AccountContext.currentUser();
    if (baseUser != null) {
      LinkappUser user = userService.findByUsername(baseUser.getUsername());
      JSONObject obj = new JSONObject();
      obj.put("user", user);
      obj.put("roles", roleService.getByUserId(user.getId()));

      if ("1".equals(user.getType())) {
        //增加PC端默认值type
        List<LinkappPrivilege> privileges = applicationService.selectApplicationPrivilegeByUser(
            user.getId().toString(), 0);
        obj.put("auth", privileges);
      } else {
        //增加PC端默认值type
        obj.put("auth", privilegeService.selectPrivilegeByUser(user.getId().toString(), 0));
      }
      //增加返回tenant信息
      String tenantId = user.getTenantId();
      if (StringUtils.isNotBlank(tenantId)){
        LinkappTenant linkappTenant = linkappTenantService.currentTenant();
        obj.put("tenantInfo",linkappTenant);
      }
      return RestBuilders.successBuilder().data(obj).build();
    } else {
      return RestBuilders.failureBuilder().message("请先登录").build();
    }
  }

  /**
   * 获取当前用户信息
   *
   * @return REST消息
   */
  @ApiOperation("获取当前用户信息")
  @GetMapping("appinfo")
  public RestMessage appinfo() {
    BaseUser baseUser = AccountContext.currentUser();
    if (baseUser != null) {
      LinkappUser user = userService.findByUsername(baseUser.getUsername());
      JSONObject obj = new JSONObject();
      obj.put("user", user);
      obj.put("roles", roleService.getByUserId(user.getId()));
      //增加app端默认值type
      if ("1".equals(user.getType())) {
        //增加PC端默认值type
        List<LinkappPrivilege> privileges = applicationService.selectApplicationPrivilegeByUser(
            user.getId().toString(), 1);
        obj.put("auth", privileges);
      } else {
        //增加PC端默认值type
        obj.put("auth", privilegeService.selectPrivilegeByUser(user.getId().toString(), 1));
      }
      //增加返回tenant信息
      String tenantId = user.getTenantId();
      if (StringUtils.isNotBlank(tenantId)){
        LinkappTenant linkappTenant = linkappTenantService.currentTenant();
        obj.put("tenantInfo",linkappTenant);
      }
      return RestBuilders.successBuilder().data(obj).build();
    } else {
      return RestBuilders.failureBuilder().message("请先登录").build();
    }
  }

  @ApiOperation("获取当前用户项目信息")
  @GetMapping("/getUserProject")
  public RestMessage getUserProject() {
    BaseUser baseUser = AccountContext.currentUser();
    if (baseUser != null) {
      LinkappUser user = userService.findByUsername(baseUser.getUsername());
      String phone = user.getPhone();
      //如果有手机号，则用手机号查所有项目信息
      JSONObject obj = new JSONObject();
      if(StringUtils.isNotBlank(phone)){
        //查询用户项目信息
        List<LinkappTenantDTO> userTenantLs = linkappTenantService.selectUserTenantByPhone(phone);
        //obj.put("user",user);
        obj.put("projectList", userTenantLs);
        return RestBuilders.successBuilder().data(obj).build();
      }else {
        //如果手机号为空，则根据当前tanetId 跟账户信息进行关联查询
        //20220711变更：排除已冻结的
        user.setLocked(false);
        List<LinkappTenantDTO> userTenantLs = linkappTenantService.selectUserTenantByUser(user);
        obj.put("projectList", userTenantLs);
        return RestBuilders.successBuilder().data(obj).build();
      }
    } else {
      return RestBuilders.failureBuilder().message("请先登录").build();
    }
  }

  @ApiOperation("选择项目")
  @PostMapping("/userSelectProject")
  @CommonOperateLogAnnotate(module = LogModule.LOGIN, desc = "")
  public void userSelectProject(@RequestBody LinkappUser appUser,
      HttpServletRequest request, HttpServletResponse response) {

    String userName = appUser.getUsername();
    //Assert.isTrue(StringUtils.isNotBlank(userName), "选择项目为空");

    if (StringUtils.isBlank(userName)) {
      //return RestBuilders.failureBuilder().code("1001").message("选择项目为空").build();
      RestMessage message = RestBuilders.successMessage("选择项目为空");
      Responses.standard(response).respond(message);
    }

    LinkappUser user = userService.findByUsername(userName);
    if (user == null) {
      //return RestBuilders.failureBuilder().code("1002").message("项目不存在").build();
      RestMessage message = RestBuilders.successMessage("项目不存在");
      Responses.standard(response).respond(message);
    }

    LinkappTenant linkappTenant = linkappTenantService.getOneById(user.getTenantId());
    LogHelper.setContent(LogOperateType.LOGIN_IN_PROJECT,linkappTenant.getPlatformProjectName());

    boolean enabled = Optional.ofNullable(user.getDisplay()).orElse(true);
    boolean accountNonLocked = !Optional.ofNullable(user.getLocked()).orElse(false);
    /*// 登录校验，验证用户可否登录
    if (enabled && accountNonLocked) {
      BeanFunctionUtils.validates(LoginValidator.class, user);
    }*/
    UserDetails userDetails = new org.springframework.security.core.userdetails.User(
        user.getUsername(),
        user.getPassword(), enabled, true, true, accountNonLocked, Collections.emptyList());

    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
        userDetails, null,
        userDetails.getAuthorities());
    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
    // 设置为已登录
    SecurityContextHolder.getContext().setAuthentication(authentication);

    //TODO 这里以后处理增加appToken机制
    user.setPassword(null);
    String userJson = JSONUtil.toJsonStr(user);
    String appToken = user.getUsername() + "-" + user.getTenantId();

    int expTime = CommonConstant.SESSION_TIME_DEFAULT * 30;

    // 加密appToken
    String enAppToken = SecureUtil.aes(CommonConstant.AesKey.getBytes()).encryptHex(appToken);

    String key = CommonConstant.appTokenKeyPre + enAppToken;

    redisUtil.set(key,userJson,expTime);

    JSONObject obj = new JSONObject();
    //obj.put("user",userJson);
    obj.put("appToken",enAppToken);

    //return RestBuilders.successBuilder().data(obj).build();
    HttpSession session = request.getSession();
    session.setMaxInactiveInterval(expTime);
    RestMessage message = RestBuilders.successBuilder().data(obj).build();
    Responses.standard(response).respond(message);

  }

  @ApiOperation("刷新用于与registionId的对应关系")
  @PostMapping("/updateRegistrationId")
  public RestMessage updateRegistrationId(@RequestBody LinkappUser appUser) {
    userService.updateRegistrationId(appUser);
    return RestBuilders.successBuilder().build();
  }
}
